﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
using System.Xml;
using System.Runtime.InteropServices;

namespace Sysmonitor
{
    public partial class SysmonitorUi : Form
    {
        [DllImport("user32.dll")]
        public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); 

        #region
        //创建NotifyIcon对象 
        NotifyIcon notifyicon = new NotifyIcon();

        //创建托盘图标对象 
        Icon ico = new Icon(@"res\\notifyIcon.ico");

        //创建托盘菜单对象 
        ContextMenu notifyContextMenu;

        #endregion

        public SysmonitorUi()
        {
            m_IsStart = false;
            m_IsExit = false;
            m_IsSysmonitor = false;
            m_LastTime = 0;
            m_index = 1;

            m_SysmonitorProcessMap = new Dictionary<String, List<Process>>();
            m_HelpUrl = "http://www.xiankai.cc";
            m_HideTip = "进程监控服务";

            m_SettingProcess = "";
            m_RestoreProcess = "";

            InitializeComponent();

            //加载启动配置
            LoadSysmonitorConf();

            //定义一个MenuItem数组，并把此数组同时赋值给ContextMenu对象 
            MenuItem[] mnuItms = new MenuItem[3];

            mnuItms[0] = new MenuItem();
            mnuItms[0].Text = "设置";
            mnuItms[0].Click += new System.EventHandler(this.DoStartSetting);
            mnuItms[0].DefaultItem = false;

            mnuItms[1] = new MenuItem();
            mnuItms[1].Text = "帮助";
            mnuItms[1].Click += new System.EventHandler(this.DoOpenWeb);
            mnuItms[1].DefaultItem = false;

            mnuItms[2] = new MenuItem();
            mnuItms[2].Text = "退出";
            mnuItms[2].Click += new System.EventHandler(this.DoExit);
            mnuItms[2].DefaultItem = true;
            notifyContextMenu = new ContextMenu(mnuItms);
            this.notifyIcon1.ContextMenu = notifyContextMenu;

            //更新进度图片
            RefreshProgress();
        }

        //加载需要启动EXE文件
        private void LoadSysmonitorConf()
        {
            m_ProcessExeList = new List<ProcessExeItem>();
            try
            {
                //初始化一个xml实例
                XmlDocument xml = new XmlDocument();

                //导入指定xml文件
                xml.Load("sysmonitor.xml");

                //获得第一个姓名匹配的节点（SelectSingleNode）：此xml文件的根节点
                XmlNode rootNode = xml.SelectSingleNode("root/processlist");
                if (rootNode != null)
                {
                    //获得该节点的子节点（即：该节点的第一层子节点）
                    XmlNodeList firstLevelNodeList = rootNode.ChildNodes;
                    foreach (XmlNode node in firstLevelNodeList)
                    {
                        ProcessExeItem tmpexe = new ProcessExeItem();

                        //判断此节点是否还有子节点
                        if (node.HasChildNodes)
                        {
                            //获取该节点的第一个子节点
                            XmlNodeList secondLevelNodelist = node.ChildNodes;
                            foreach (XmlNode nodelevel2 in secondLevelNodelist)
                            {
                                //获取该节点的名字
                                if (nodelevel2.Name == "startcmd")
                                {
                                    tmpexe.m_StartCmd = nodelevel2.InnerText;
                                }
                                else if (nodelevel2.Name == "processname")
                                {
                                    tmpexe.m_ProcessName = nodelevel2.InnerText;
                                }
                                else if (nodelevel2.Name == "failtip")
                                {
                                    tmpexe.m_FailTip = nodelevel2.InnerText;
                                }
                                else
                                {
                                    Console.WriteLine("{0}", nodelevel2.Name);
                                }
                            }

                            m_ProcessExeList.Add(tmpexe);
                        }
                    }
                }

                //获得第一个姓名匹配的节点（SelectSingleNode）：此xml文件的根节点
                rootNode = xml.SelectSingleNode("root/serverconf");
                if (rootNode != null)
                {
                    XmlNodeList firstLevelNodeList = rootNode.ChildNodes;
                    foreach (XmlNode node in firstLevelNodeList)
                    {
                        //获取该节点的名字
                        if (node.Name == "helpurl")
                        {
                            m_HelpUrl = node.InnerText;
                        }
                        else if (node.Name == "hidetip")
                        {
                            m_HideTip = node.InnerText;
                        }
                        else if (node.Name == "setstartprocess")
                        {
                            m_SettingProcess = node.InnerText;
                        }
                        else if (node.Name == "restoreprocess")
                        {
                            m_RestoreProcess = node.InnerText;
                        }
                        else
                        {
                            Console.WriteLine("{0}", node.Name);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        public void DoExit(object sender, System.EventArgs e)
        {
            //停止定时器
            this.timer1.Enabled = false;

            //停止进程
            foreach (var process in m_SysmonitorProcessMap)
            {
                foreach (var exe in process.Value)
                {
                    if (!exe.HasExited)
                    {
                        if (!exe.CloseMainWindow())
                        {
                            exe.Kill();
                            exe.WaitForExit(5000);
                            if (!exe.HasExited)
                            {
                                Thread.Sleep(3000);
                                exe.Kill();
                                exe.WaitForExit(5000);
                            }
                        }
                    }
                }

            }

            //隐藏托盘程序中的图标 
            this.notifyIcon1.Visible = false;

            //关闭系统 
            this.Close();
            this.Dispose(true);
        }

        public void DoOpenWeb(object sender, System.EventArgs e)
        {
            //调用系统默认的浏览器 
            System.Diagnostics.Process.Start(m_HelpUrl);
        }

        public void DoStartSetting(object sender, System.EventArgs e)
        {
            //启动设置界面
            if (m_SettingProcess != "" )
            {
                //在所有已启动的进程中查找需要的进程；
                Process[] temp = Process.GetProcessesByName(m_SettingProcess);
                if (temp.Length > 0)//如果查找到
                {
                    IntPtr handle = temp[0].MainWindowHandle;
                    SwitchToThisWindow(handle, true); // 激活，显示在最前
                }
                else
                {
                    System.Diagnostics.ProcessStartInfo Infoweb = new System.Diagnostics.ProcessStartInfo();

                    //设置外部程序名
                    Infoweb.FileName = m_SettingProcess+".exe";
                    System.Diagnostics.Process.Start(Infoweb);
                }
            }
        }

        //启动进程
        private void StartExecutable()
        {
            foreach (var process in m_ProcessExeList)
            {
                if (!IsExistProcess(process.m_ProcessName) && !IsExistProcess(process.m_ProcessName.ToUpper()))
                {
                    StartProcess(process.m_StartCmd);
                }

                int count = 0;
                while(count < 4)
                {
                    if (!IsExistProcess(process.m_ProcessName) && !IsExistProcess(process.m_ProcessName.ToUpper()))
                    {
                        if (count > 2)
                        {
                            MessageBox.Show(process.m_FailTip);
                            m_IsExit = true;
                            return;
                        }

                        count++;
                    }
                    else
                    {
                        break;
                    }

                    Thread.Sleep(10000);
                }
            }

            //获取进程信息
            CollectAllProcess();

            m_LastTime = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;
            m_IsExit = true;
        }

        //进程检测
        private void CheckProcess()
        {
            double now = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;
            if(now - m_LastTime > 30000)
            {
                foreach (var process in m_ProcessExeList)
                {
                    if (!IsExistProcess(process.m_ProcessName) && !IsExistProcess(process.m_ProcessName.ToUpper()))
                    {
                        StartProcess(process.m_StartCmd);
                    }
                }

                //收集进程信息
                CollectAllProcess();

                m_LastTime = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;
            }

            return;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (m_IsExit)
            {
                if (!m_IsSysmonitor)
                {
                    //this.Close();
                    //托盘显示图标等于托盘图标对象 
                    //注意notifyIcon1是控件的名字而不是对象的名字 
                    //设置鼠标放在托盘图标上面的文字 
                    this.notifyIcon1.Text = m_HideTip;
                    this.notifyIcon1.Icon = ico;

                    //图标显示在托盘区 
                    notifyicon.Visible = true;

                    //隐藏窗体
                    this.Hide();

                    //隐藏任务栏区图标 
                    this.ShowInTaskbar = false;

                    m_IsSysmonitor = true;
                }
                else
                {
                    //检查进程
                    CheckProcess();
                }

                return;
            }

            //判断是否启动线程
            if (!m_IsStart)
            {
                Thread threadC = new Thread(StartExecutable);
                threadC.Start();
                m_IsStart = true;
            }

            //刷新新进度
            RefreshProgress();
        }

        private bool IsExistProcess(string processName)
        {
            Process[] MyProcesses = Process.GetProcesses();
            foreach (Process MyProcess in MyProcesses)
            {
                if (MyProcess.ProcessName.CompareTo(processName) == 0)
                {
                    return true;
                }
            }
            return false;
        }

        private void CollectAllProcess()
        {
            Process[] MyProcesses = Process.GetProcesses();
            foreach (var process in m_ProcessExeList)
            {
                List<Process> tmpprocess = new List<Process>();
                foreach (Process MyProcess in MyProcesses)
                {
                    if (MyProcess.ProcessName.CompareTo(process.m_ProcessName) == 0 ||
                        MyProcess.ProcessName.CompareTo(process.m_ProcessName.ToUpper()) == 0)
                    {
                        tmpprocess.Add(MyProcess);
                    }
                }

                if (tmpprocess.Count > 0)
                {
                    if (m_SysmonitorProcessMap.ContainsKey(process.m_ProcessName))
                    {
                        m_SysmonitorProcessMap[process.m_ProcessName].Clear();
                        m_SysmonitorProcessMap[process.m_ProcessName] = null;
                        m_SysmonitorProcessMap.Remove(process.m_ProcessName);
                    }

                    m_SysmonitorProcessMap[process.m_ProcessName] = tmpprocess;
                }
                else
                {
                    tmpprocess = null;
                }
            }
        }

        private void StartProcess(string processName)
        {
            System.Diagnostics.ProcessStartInfo Infoweb = new System.Diagnostics.ProcessStartInfo();

            //设置外部程序名
            Infoweb.FileName = processName;

            //设置隐藏窗口
            Infoweb.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            System.Diagnostics.Process.Start(Infoweb);

            Thread.Sleep(3000);
        }

        private void RefreshProgress()
        {
            if (m_index == 1)
            {
                try
                {
                    Image tmpimage = Image.FromFile(@"res\\start01.jpg");
                    this.BackgroundImage = tmpimage;
                }
                catch (Exception ex)
                {
                    this.BackgroundImage = global::Sysmonitor.Properties.Resources.start01;
                }
                m_index++;
            }
            else if (m_index == 2)
            {
                try
                {
                    Image tmpimage = Image.FromFile(@"res\\start02.jpg");
                    this.BackgroundImage = tmpimage;
                }
                catch (Exception ex)
                {
                    this.BackgroundImage = global::Sysmonitor.Properties.Resources.start02;
                }
                m_index++;
            }
            else
            {
                try
                {
                    Image tmpimage = Image.FromFile(@"res\\start03.jpg");
                    this.BackgroundImage = tmpimage;
                }
                catch (Exception ex)
                {
                    this.BackgroundImage = global::Sysmonitor.Properties.Resources.start03;
                }
                m_index = 1;
            }

            this.Show();
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (m_RestoreProcess != "")
            {
                //在所有已启动的进程中查找需要的进程；
                Process[] temp = Process.GetProcessesByName(m_RestoreProcess);
                if (temp.Length > 0)//如果查找到
                {
                    IntPtr handle = temp[0].MainWindowHandle;
                    SwitchToThisWindow(handle, true); // 激活，显示在最前
                }
                else
                {
                    System.Diagnostics.ProcessStartInfo Infoweb = new System.Diagnostics.ProcessStartInfo();

                    //设置外部程序名
                    Infoweb.FileName = m_RestoreProcess + ".exe";
                    System.Diagnostics.Process.Start(Infoweb);
                }
            }
        }

        private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
        {
            switch (e.Button)
            {
                case System.Windows.Forms.MouseButtons.Left:    //左击
                    //启动设置界面

                    break;
                case System.Windows.Forms.MouseButtons.Right:
                    //MessageBox.Show("右键");
                    break;
            }
        }
    }
}
